/* * JBoss, Home of Professional Open Source * Copyright 2011, Red Hat and individual contributors * by the @authors tag. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * * @authors Andrew Dinn */ package org.jboss.jokre.agent; import java.io.File; import java.io.IOException; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import java.util.jar.JarFile; /** * Agent main program for Jokre bytecode optimizer. */ public class Main { /** * prefix used to specify boot jar argument for agent */ private static final String BOOT_PREFIX = "boot:"; /** * prefix used to specify system jar argument for agent */ private static final String SYS_PREFIX = "sys:"; /** * list of paths to extra bootstrap jars supplied on command line */ private static List<String> bootJarPaths = new ArrayList<String>(); /** * list of paths to extra system jars supplied on command line */ private static List<String> sysJarPaths = new ArrayList<String>(); /** * flag used to void repeated agent loads */ private static boolean firstTime = true; public static void premain(String args, Instrumentation inst) throws Exception { // guard against the agent being loaded twice synchronized (Main.class) { if (firstTime) { firstTime = false; } else { throw new Exception("org.jboss.jokre.agent.Main : attempting to load Jokre agent more than once"); } } if (args != null) { // args are supplied separated by ',' characters String[] argsArray = args.split(","); // we accept extra jar files to be added to the boot/sys classpaths // script files to be scanned for rules // listener flag which implies use of a retransformer for (String arg : argsArray) { if (arg.startsWith(BOOT_PREFIX)) { bootJarPaths.add(arg.substring(BOOT_PREFIX.length(), arg.length())); } else if (arg.startsWith(SYS_PREFIX)) { sysJarPaths.add(arg.substring(SYS_PREFIX.length(), arg.length())); } else { System.err.println("org.jboss.jokre.agent.Main:\n" + " illegal agent argument : " + arg + "\n" + " valid arguments are boot:<path-to-jar> or sys:<path-to-jar>"); } } } // add any boot jars to the boot class path for (String bootJarPath : bootJarPaths) { try { JarFile jarfile = new JarFile(new File(bootJarPath)); inst.appendToBootstrapClassLoaderSearch(jarfile); } catch (IOException ioe) { System.err.println("org.jboss.jokre.agent.Main: unable to open boot jar file : " + bootJarPath); throw ioe; } } // add any sys jars to the system class path for (String sysJarPath : sysJarPaths) { try { JarFile jarfile = new JarFile(new File(sysJarPath)); inst.appendToSystemClassLoaderSearch(jarfile); } catch (IOException ioe) { System.err.println("org.jboss.jokre.agent.Main: unable to open system jar file : " + sysJarPath); throw ioe; } } // install a transformer to do call site transformations boolean isRetransform = inst.isRetransformClassesSupported(); if (!isRetransform) { throw new Exception("org.jboss.jokre.agent.Main : JVM does not support retransformation"); } ClassFileTransformer transformer; ClassLoader loader = ClassLoader.getSystemClassLoader(); Class transformerClazz; // create the Jokre agent via reflection in case we want to put the Jokre lib into the bootstrap classpath //transformer = new Jokre(inst); transformerClazz = loader.loadClass("org.jboss.jokre.agent.Jokre"); Constructor constructor = transformerClazz.getConstructor(Instrumentation.class); transformer = (ClassFileTransformer)constructor.newInstance(new Object[] { inst }); inst.addTransformer(transformer, true); } public static void agentmain(String args, Instrumentation inst) throws Exception { premain(args, inst); } }